var path = require('path');
var log4js = require(path.resolve(__dirname, '../config/logger'));
var logger = log4js.getLogger('status');
var DbCommon = require('./db');
const Atom = require('./atom');
const jsdom = require("jsdom");
const Opreators = require('./operator');
const Observer = require('./observe');
const {
  JSDOM
} = jsdom;

const calcOpreator = function(opreator, data, key) {
  if (Opreators.hasOwnProperty(opreator)) {
    return Opreators[opreator](data, key)
  } else {
    let i = opreator.indexOf('(');
    let j = opreator.indexOf(')');
    let name = opreator.substring(0, i);
    if (i > 0 && j > 0 && Opreators.hasOwnProperty(name)) {
      let param = opreator.substring(i + 1, j);
      if (!isNaN(param)) {
        param = Number(param);
      }
      return Opreators[name](data, key, param)
    } else {
      return ''
    }
  }
}
class Phrase {
  constructor(id) {
    this.id = id;
    this.name = '';
    this.template = '';
    this.status = 1;
    this.dom = null;
    this.atomsMap = {};
    // 添加了全局上下文的原子和参数
    this.globalContextAtoms = [];
    this.atomParams = [];
    this.atomOpreators = [];
    this.autoParams = {};
    this.content = '';
    this._logicCache = {};
    this.data = null;
    this.force = false;
  }
  init() {
    var that = this;
    return new Promise(function (resolve, reject) {
      let wheres = [{
        type: 1,
        key: 'id',
        value: that.id
      }]
      let sqlOptions = {
        wheres: wheres,
        table: 'phrase'
      }
      if (that.id) {
        DbCommon.getDataById(sqlOptions).then(function (data) {
          if (data.length > 0) {
            that.name = data[0].name;
            that.status = data[0].status;
            that.template = data[0].template;
            resolve();
          } else {
            reject(new Error('no data find'));
          }
        }).catch(function (error) {
          reject(error);
        });
      } else {
        resolve();
      }
    })
  }
  // 传入变动参数
  setAutoParams(autoParams) {
    this.autoParams = autoParams || {};
  }
  setForce(force) {
    this.force = force;
  }
  getContent() {
    var that = this;
    return new Promise(function (resolve, reject) {
      that.init().then(function () {
        let promiseArrs = [];
        that.parseTemplate();
        let serialRequest = [];
//      console.log(that.atomsMap, "222222");  {'616':{id: "616", name:'', parameters:'', urls:'', type:'', kind:''}, '716':{..}}
        for (const key in that.atomsMap) {
          that.atomsMap[key].setForce(that.force);
          serialRequest.push(that.atomsMap[key]);
          //promiseArrs.push(that.atomsMap[key].getContent())
        }
        let index = 0;
        let length = serialRequest.length;
        const atomGo = function() {
          if (index == length) {
            that.getRealContent();
            resolve('ok');
          } else {
            serialRequest[index].getContent().then(function(result) {
              that.setGlobalContextParams(serialRequest[index]);
              //logger.info(serialRequest[index].gridContent);
              index++;
              atomGo();
            }).catch(function(error) {
              reject(error);
            })
          }
        }
        atomGo();
        // Promise.all(promiseArrs).then(function (result) {
        //   that.getRealContent();
        //   resolve('ok');
        // }).catch(function (err) {
        //   reject(err);
        // })
      }).catch(function (error) {
        reject(error);
      })
    })
  }
  setGlobalContextParams(atom) {
    if (atom && atom.id) {
      for (let index = 0; index < this.globalContextAtoms.length; index++) {
        const element = this.globalContextAtoms[index];
        if (element.atomId == atom.id ) {
          let value = '';
          let key = element.paramName;
          if (atom.data && atom.data instanceof Array && atom.data.length > 0) {
            value = atom.data[0][key];
          } else if (atom.data) {
            value = atom.data[key];
          }
          //console.log(atom.id + '&&' + key + '&&' + value + '&&' + JSON.stringify(atom.data));
          Observer.addContextParams(key, value);
          break;
        }
      }
    }
  }
  parseTemplate() {
    if (this.template.length) {
      //替换掉模板标识符
      this.template = this.template.replace(/@<strong/ig, '<strong').replace(/strong>\.<strong/ig, 'strong><strong').replace(/>\|<strong/ig, '><strong');
      let html = `<!DOCTYPE html><div>${this.template}</div>`;
      // console.log(html);
      this.dom = new JSDOM(html);
      let atomDoms = this.dom.window.document.querySelectorAll('.quill-atom');  //获取所有原子
      let atomParameterDoms = this.dom.window.document.querySelectorAll('.quill-atom-param');  //获取所有原子后的.
      let opreatorDoms = this.dom.window.document.querySelectorAll('.quill-atom-operator');
//    console.log(atomDoms, "11111")  [ HtmlElemnt{}, HtmlElemnt{}, HtmlElemnt{}, HtmlElemnt{}, HtmlElemnt{}]
      atomDoms.forEach(element => {
        let id = element.getAttribute('_id');
//      console.log(id, "7777")  616 616 616 716 716
        if (!this.atomsMap[id]) {
          this.atomsMap[id] = new Atom(id);
          this.atomsMap[id].setAutoParams(this.autoParams);
        }
      });
      atomParameterDoms.forEach(element => {
        let id = element.getAttribute('_id');
        let atomId = element.getAttribute('_atomid');
        let name = element.getAttribute('_name');
        let atomParam = {
          id: id,
          atomId: atomId,
          name: name
        };
        this.atomParams.push(atomParam);
      })
      opreatorDoms.forEach(element => {
        let tid = element.getAttribute('_tid');
        let name = element.getAttribute('_name');
        this.atomOpreators.push({
          tid: tid,
          name: name
        })
        // 全局上下文的算子,单独处理
        if (name == 'globalContext') {
          let atomParamElements = this.dom.window.document.querySelectorAll('.quill-atom-param[_uid="' + tid + '"]');
          if (atomParamElements.length > 0) {
            let atomParamElement = atomParamElements[0];
            let atomId = atomParamElement.getAttribute('_atomid');
            let name = atomParamElement.getAttribute('_name');
            this.globalContextAtoms.push({
              atomId: atomId,
              paramName: name
            })
          }
        }
      })
    }
  }
  getRealContent() {
    if (this.dom) {
      let content = this.dom.window.document.body.innerHTML;
      
      content = content.replace(/&lt;/g, '<').replace(/&gt;/g, '>');
//   	let tar = Object.keys(this.atomsMap).filter(item => {
//   		return this.atomsMap[item].type == 6
//   	});
      let logicFors = content.match(/<%for([\w\W]+?)%\/for%>/g);
      if (logicFors && logicFors.length > 0) {
        logicFors.forEach(code => {
          let condition = code.match(/<%for\s\((.+?)\)%>/);
          if (condition && condition.length > 1) {
            condition = condition[1];  //拿到for的元素
            let con_key = '';
            let atomId = '';
            let param_name = '';
            let opreator = '';
            let data = [];
            let res = '';

            // 正则提取原子id
            let matchs = condition.match(/(?:quill-atom).+?(_id="(\d+)")/);
            if (matchs && matchs.length == 3) {
              atomId = matchs[2];
              con_key = con_key + atomId;
              data = this.atomsMap[atomId].data;
            }
            // 正则提取原子参数
            matchs = condition.match(/(?:quill-atom-param).+?_id="\d+".+?(_name="(.+?)")/);
            if (matchs && matchs.length == 3) {
              param_name = matchs[2];
              con_key = con_key + '-' + param_name;
            }
            // 正则提取原子算子名称operator
            matchs = condition.match(/(?:quill-atom-operator).+?_id="\d+".+?(_name="(.+?)")/);
            if (matchs && matchs.length == 3) {
              opreator = matchs[2];
              con_key = con_key + '-' + opreator;
              data = calcOpreator(opreator, data, param_name)
              //data = Opreators[opreator](data, param_name);
            }
            if (data instanceof Array && data.length > 0) {
              data.forEach((d, num) => {
                let stances = code.match(/{{(.+?)}}/g);  //全局匹配前后有两组花括号的
                let str_content = code.match(/%>(.+?)<%\//); //获取%>到<%/之间的
                if (str_content && str_content.length == 2) {
                  str_content = str_content[1];
                };
                stances.forEach(stance => {  //一个{{}}内的内容
                  let s_html = stance.match(/{{(.+?)}}/);
                  if (s_html && s_html.length == 2) {
                    s_html = s_html[1];
                  };
                  let atomId = s_html.match(/_id="(\S*)"/)[1];
                  let tarAtom = this.atomsMap[atomId];
              		if(tarAtom.type == 6){
              			logger.info('for循环里有表格'+ atomId);
	                  if (d == undefined) {
	                    str_content = str_content.replace('{{' + s_html + '}}', '');
	                  } else {
                    	let parameters = Object.assign([], this.atomsMap[atomId].parameters);
                    	
        	  					let intable_params = parameters.filter(item => {
								        return item.is_intable;
								      });
								      let is_intable_params = intable_params.sort((a, b) => {
								        return a.t_index - b.t_index;
								      });
								      let className = `table_column${is_intable_params.length}`;
											let str = `<div class="xg_table_wrapper"><table class="${className}"><tbody>`;
								      is_intable_params.forEach((element, index) => {
								        str += `<tr><th>${element.alias_name}</th>`;
								        let tarItem = is_intable_params[index];
								        let value = d[tarItem.name];
								        if (tarItem.operator) {
								          value = Opreators[tarItem.operator]([d], tarItem.name)
								        };
								        str += `<td>${value}</td></tr>`;
								      });
								      str += `</tbody></table></div>`;
											if (d.length == 0) {
								        str = `<div></div>`;
								     	};
                    	str_content = str_content.replace('{{' + s_html + '}}', str);
	                  }
                  } else if(tarAtom.type == 2 && tarAtom.kind == 2){
              			logger.info('for循环里有串行表格'+ atomId);
              			let tar = this.atomsMap[atomId].data;
	                  if (d == undefined) {
	                    str_content = str_content.replace('{{' + s_html + '}}', '');
	                  } else {
                    	let parameters = Object.assign([], this.atomsMap[atomId].parameters);
        	  					let intable_params = parameters.filter(item => {
								        return item.is_intable;
								      });
								      let is_intable_params = intable_params.sort((a, b) => {
								        return a.t_index - b.t_index;
								      });
								      let className = `table_column${is_intable_params.length}`;
											let str = `<div class="xg_table_wrapper"><table class="${className}"><thead><tr>`;
								      is_intable_params.forEach(element => {
							        	str += `<th>${element.alias_name}</th>`;
								      });
								      str += `</tr></thead><tbody>`;
							        tar[num].forEach(item => {
							          str += `<tr>`;
							          is_intable_params.forEach(element => {
							            let value = item[element.name];
							            if (element.operator) {
							              value = Opreators[element.operator]([item], element.name)
							            }
							            str += `<td>${value}</td>`;
							          });
							          str += `</tr>`;
							        })
								      str += `</tbody></table></div>`;
											if (d.length == 0) {
								        str = `<div></div>`;
								     	};
                    	str_content = str_content.replace('{{' + s_html + '}}', str);
	                  }
                  } else {
	                  let opreator = '';
	                  let param_name = '';
	                  let matchs = null;
	                  matchs = s_html.match(/(?:quill-atom-param).+?_id="\d+".+?(_name="(.+?)")/);
	                  if (matchs && matchs.length == 3) {
	                    param_name = matchs[2];  //sec_name
	                  }
	                  matchs = s_html.match(/(?:quill-atom-operator).+?_id="\d+".+?(_name="(.+?)")/);
	                  if (matchs && matchs.length == 3) {
	                    opreator = matchs[2];
	                  }
	                  if (d == undefined) {
	                    str_content = str_content.replace('{{' + s_html + '}}', '');
	                  } else {
	                    if (d instanceof Array) {
	                      if (opreator) {
	                        let val = calcOpreator(opreator, d, param_name);
	                        let r = '';
	                        if (val instanceof Array) {
	                          r = val[0] ? val[0][param_name] : '';
	                        } else {
	                          r = val
	                        }
	                        str_content = str_content.replace('{{' + s_html + '}}', r);
	                      } else {
	
	                        let val = d[0] ? d[0][param_name] : '';
	                        str_content = str_content.replace('{{' + s_html + '}}', val);
	                      }
	                    } else {
	                      //console.log('str_content', str_content);
	                      if (opreator) {
	                        //console.log(opreator,d,param_name)
	                        str_content = str_content.replace('{{' + s_html + '}}', calcOpreator(opreator, [d], param_name));
	                      } else {
	                        str_content = str_content.replace('{{' + s_html + '}}', d[param_name]);
	                      }
	                    }
	                  }
                  }
                })
                res += str_content;
              })
              res = res.replace(/\s/g, '');
              res = res.replace(/class/g, ' class');
//            res = res.replace(/xg_scroll_wrapper/g, ' xg_scroll_wrapper');
              res = res.replace(/colspan/g, ' colspan');
              res = res.replace(/rowspan/g, ' rowspan');
              res = res.replace(/style/g, ' style');
              content = content.replace(code, res.substring(0, res.length - 1));
            } else {
              content = content.replace(code, '');
            }
          } else {
            content = content.replace(code, '');
          }
        })
        this.dom.window.document.body.innerHTML = content;
      }
      //console.log(this.dom.window.document.body.innerHTML);
      let opreatorDoms = this.dom.window.document.querySelectorAll('.quill-atom-operator');
      opreatorDoms.forEach(element => {
        let tid = element.getAttribute('_tid');
        let key = element.getAttribute('_name');
        //let opreator = Opreators[key];
        let atomParamElements = this.dom.window.document.querySelectorAll('.quill-atom-param[_uid="' + tid + '"]');
        if (atomParamElements.length > 0) {
          let atomParamElement = atomParamElements[0];
          let atomId = atomParamElement.getAttribute('_atomid');
          let name = atomParamElement.getAttribute('_name');
          let value = '';
          // console.log(this.atomsMap[atomId].data);
          // console.log(key);
          // console.log(name);
          if (this.atomsMap[atomId].data && this.atomsMap[atomId].data instanceof Array) {
            value = calcOpreator(key, this.atomsMap[atomId].data, name)
            //value = opreator(this.atomsMap[atomId].data, name);
          } else if (this.atomsMap[atomId].data) {
            value = calcOpreator(key, [this.atomsMap[atomId].data], name)
            //value = opreator([this.atomsMap[atomId].data], name);
          } 
          //console.log(value);
          // 存储 原子经过算子计算的结果 
          let dataKey = atomId + '-' + name + '-' + key;
          this.atomsMap[dataKey] = value;
          //console.log(value);
          if (this.atomsMap[atomId].type > 1 && atomParamElement.previousSibling && atomParamElement.previousSibling.className.indexOf('quill-atom') > -1) {
            if (value instanceof Array) {
              let gridContent = this.atomsMap[atomId].generateGrid(this.atomsMap[atomId].type, value, true);
              atomParamElement.previousSibling.outerHTML = `${gridContent}`;
              atomParamElement.outerHTML = '';
              element.outerHTML = '';
            }
          } else if (!(value instanceof Array) && this.atomsMap[atomId].type == 1) {
            element.outerHTML = `<span>${value}</span>`;
            atomParamElement.previousSibling.outerHTML = '';
            atomParamElement.outerHTML = '';
          } else if (value instanceof Array && this.atomsMap[atomId].type == 1) {
            
            element.outerHTML = `<span _atomid="${atomId}" data-length="${value.length}"></span>`;
            atomParamElement.previousSibling.outerHTML = '';
            atomParamElement.outerHTML = '';
          }
        }
      })
      let atomDoms = this.dom.window.document.querySelectorAll('.quill-atom');

      // logger.info(atomDoms);
      //console.log(this.dom.window.document.body.innerHTML);
      atomDoms.forEach(element => {
        let id = element.getAttribute('_id');
        let uid = element.getAttribute('_uid');
        //console.log(id + uid);
        if (this.dom.window.document.querySelectorAll('.quill-atom[_uid="' + uid + '"]').length > 0) {
          if (this.atomsMap[id].type == 1) {
            element.outerHTML = ``;
          } else{
            let gridContent = this.atomsMap[id].gridContent;
            element.outerHTML = `${gridContent}`;
          }
        }
        //文本类型原子
      });
      //console.log(this.dom.window.document.body.innerHTML);
      let atomParameterDoms = this.dom.window.document.querySelectorAll('.quill-atom-param');
      atomParameterDoms.forEach(element => {
        let id = element.getAttribute('_id');
        let atomId = element.getAttribute('_atomid');
        let name = element.getAttribute('_name');
        let value = '';

        if (this.atomsMap[atomId].data instanceof Array && this.atomsMap[atomId].data.length > 0) {
          value = this.atomsMap[atomId].data[0][name];
        } else if (this.atomsMap[atomId].data) {
          value = this.atomsMap[atomId].data[name] || '';
        }
        element.outerHTML = `<span>${value}</span>`;
      })

      //this.dom.window.document.body.children[0].style = "margin-bottom: 8px; line-height: 1.2";
      for (const key in this.dom.window.document.body.children[0].children) {
        if (this.dom.window.document.body.children[0].children.hasOwnProperty(key)) {
          const item = this.dom.window.document.body.children[0].children[key];
          if (item.tagName == 'P' && item.innerHTML.length > 0) {
            //item.style = "margin-bottom: 8px;"
          }
        }
      }
      this.content = this.dom.window.document.body.innerHTML;

   
      this.resolveLogicContent();
     
      this.removeBlank();
   
    }
  }
  resolveLogicContent() {
    if (this.content) {
      // 替换<>
      console.log(this.content);
      this.content = this.content.replace(/&lt;/g, '<').replace(/&gt;/g, '>');
      // 处理if
      //console.log(this.content);
      let ifLogics = this.content.match(/<%if([\w\W]+?)%\/if%>/g);
      if (ifLogics && ifLogics.length > 0) {
        //console.log(ifLogics);
        ifLogics.forEach(code => {
          //提取 if else 语句
          let yesOrNo = [];
          let statements = code.split('<%else%>');
          let ret = '';
          statements.forEach(item => {
            yesOrNo.push(item.replace(/<%[\w\W]+?%>/, ""));
          })
          // console.log(yesOrNo);
          // 提取if判断条件
          let condition = code.replace(/\s/g, "").match(/<%if\((.+?)\)%>/);
          if (condition && condition.length > 1) {
            condition = condition[1];   //"<span>-1.86</span>>0"
            if (condition.indexOf('data-length') > -1) {  //存在data-length
              condition = condition.match(/data-length="(.+?)">/);
              if (condition && condition.length > 1) {
                condition = condition[1]
              } else {
                condition = '';
              }
            } else {
              condition = condition.replace(/<[\w\W]+?>/g, '');
            }
            // 去除条件字符串中的标签
            condition = condition.replace(/&amp;/g, "&");
//          logger.info('condition'+ condition);
            let fucStr = 'return ' + condition;
            console.log('func str:::' + typeof(fucStr) + ':::' + fucStr);
            try {
              let func = new Function(fucStr);
              if (func() && yesOrNo.length > 1) {
                ret = yesOrNo[0];
              } else if (!func() && yesOrNo.length > 1) {
                ret = yesOrNo[1];
              }
              //console.log(ret)
            } catch (err) {
              if (typeof(condition) == 'string' && condition && yesOrNo.length > 1) {
                ret = yesOrNo[0];
              } else {
                ret = yesOrNo[1] || '';
              }
            }
            if (ret.length > 0) {
              // 替换最后判断得到语句
              ret = ret.replace(/\s/g, '');
              ret = ret.replace(/class/g, ' class');
//            ret = ret.replace(/xg_scroll_wrapper/g, ' xg_scroll_wrapper');
              ret = ret.replace(/colspan/g, ' colspan');
              ret = ret.replace(/rowspan/g, ' rowspan');
              ret = ret.replace(/style/g, ' style');
              this.content = this.content.replace(code, ret);
            }
            //console.log(this.content)
          }
        })
        // 去除多余的段落标签
        //console.log(this.content);
        //this.content = this.content.replace(/<p(.+?)>/g, '').replace(/<\/p>/g, '');
        //console.log(this.content);
      }
    }
  }
  removeBlank() {
    if (this.content) {
      let blanks = this.content.match(/>(.+?)</g);
      if (blanks) {
        blanks.forEach(code => {
          let trimCode = code.replace(/\s/g, '');
          this.content.replace(code, trimCode);
        })
      }
    }
  }
}

module.exports = Phrase;